#ifndef _INT128_INCLUDE_
#define _INT128_INCLUDE_

#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdarg.h>

// 128 bits integer
class tInt128
{
public:
	unsigned long long m_High64;
	unsigned long long m_Low64;
	mutable char m_szHexString[33];	//32 char + 1 zero.
	mutable wchar_t m_szWHexString[66];

	tInt128():m_High64(0), m_Low64(0)
	{
	}
	tInt128(const tInt128 & i)
	{
		m_High64 = i.m_High64;
		m_Low64 = i.m_Low64;
	}
	tInt128(const unsigned long long ll)
	{
		m_Low64 = ll;
		m_High64 = 0;
	}
	tInt128 & operator=(const tInt128 & i)
	{
		m_Low64 = i.m_Low64;
		m_High64 = i.m_High64;
		return *this;
	}
	tInt128 & operator=(const unsigned long long ll)
	{
		m_Low64 = ll;
		m_High64 = 0;
		return *this;
	}
	bool operator == (const tInt128 & i) const
	{
		return (m_Low64 == i.m_Low64 && m_High64 == i.m_High64);
	}
	bool operator != (const tInt128 & i) const
	{
		return (m_Low64 != i.m_Low64 || m_High64 != i.m_High64);
	}
	bool operator < (const tInt128 & i) const
	{
		if (m_High64 < i.m_High64)
			return true;
		else if (m_High64 == i.m_High64)
		{
			return m_Low64 < i.m_Low64;
		}
		else
			return false;
	}
	bool operator > (const tInt128 & i) const
	{
		if (m_High64 > i.m_High64)
			return true;
		else if (m_High64 == i.m_High64)
		{
			return m_Low64 > i.m_Low64;
		}
		else
			return false;
	}
	const char * ToString() const 
	{
#ifndef _linux_
		sprintf_s(m_szHexString, 17, "%016llx", m_High64);
		sprintf_s(m_szHexString + 16, 17, "%016llx", m_Low64);
#else
		
		sprintf(m_szHexString, "%016llx", m_High64);
		sprintf(m_szHexString + 16, "%016llx", m_Low64);
#endif
		return m_szHexString;
	}
	const wchar_t * ToWideString() const
	{
#ifndef _linux_
		swprintf_s(m_szWHexString, 17, L"%016llx", m_High64);
		swprintf_s(m_szWHexString + 16, 17, L"%016llx", m_Low64);
#else
		swprintf(m_szWHexString, 17, L"%016llx", m_High64);
		swprintf(m_szWHexString + 16, 17, L"%016llx", m_Low64);
#endif
		return m_szWHexString;
	}
	tInt128 & FromString(const char * str)
	{
		for (int i = 0; i < 2 ; i++)
		{
			for (int u = 0; u < 16; u++)
			{
				char c = str[i*16+u];
				char b = 0;
				if ( c >= 0x30 && c <= 0x39)
					b = c - 0x30;
				else if (c >= 0x41 && c <= 0x46)
					b = c - 0x37;
				else if (c >= 0x61 && c <= 0x66)
					b = c - 0x57;
				else 
				{
					m_Low64 = m_High64 = 0;
					return *this;
				}
				if (i == 0)
				{
					m_High64 <<= 4;
					m_High64 |= b;
				}
				else
				{
					m_Low64 <<= 4;
					m_Low64 |= b;
				}
			}
		}
		return *this;
	}
	tInt128 & FromBytes(unsigned char * bytes)
	{
		m_Low64 = m_High64 = 0;
		unsigned int index = 0;
		for (index = 0; index < 8; index++)
		{
			m_High64 <<= 8;
			m_High64 |= bytes[index];
		}
		for (; index < 16; index++)
		{
			m_Low64 <<= 8;
			m_Low64 |= bytes[index];
		}
		return *this;
	}
	int size()
	{
		return 16;
	}
};



#endif
